﻿using KqAutoDesign.Base;
using KqAutoDesign.Models;
using KqAutoDesign.SonViews;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Linq;
using static System.Net.Mime.MediaTypeNames;

namespace KqAutoDesign
{
    internal class MainWindowsVm
    {
        private Window _parentWindow;
        public ProjectInfo Project { get; set; }
        #region 任务列表操作
        public ICommand SetDirCommand { get; set; }
        public ICommand NewCommand { get; set; }
        public ICommand CopyCommand { get; set; }
        public ICommand DeleteCommand { get; set; } 
        public ICommand SettingsCmd { get; set; }
        #endregion
        #region 执行队列操作
        /// <summary>
        /// 加入队列操作
        /// </summary>
        public ICommand AddToQueueCmd { get; set; }
        /// <summary>
        /// 从队列移除操作
        /// </summary>
        public ICommand RemoveFromQueueCmd { get; set; }
        /// <summary>
        /// 开始执行队列
        /// </summary>
        public ICommand StartQueueCmd { get; set; }
        /// <summary>
        /// 暂停队列
        /// </summary>
        public ICommand SuspendQueueCmd { get; set; }
        /// <summary>
        /// 继续执行队列
        /// </summary>
        public ICommand GoOnQueueCmd { get; set; }
        /// <summary>
        /// 终止队列
        /// </summary>
        public ICommand StopQueueCmd { get; set; }
        #endregion
        BackgroundWorker _bgw;
        public MainWindowsVm(Window parent) 
        {
            _parentWindow = parent;
            Project = new ProjectInfo();
            GlobalData.Projects.Add(Project);
            SetDirCommand = new SimpleCommand<object>(CanSetDirExecute,SetDirExecute);
            CopyCommand = new SimpleCommand<object>(CanCopyExecute,CopyExecute);
            NewCommand = new SimpleCommand<object>(CanNewWorkExecute, NewWorkExecute);
            DeleteCommand = new SimpleCommand<object>(CanDeleteExecute, DeleteExecute);
            SettingsCmd = new SimpleCommand<object>(CanSettingsOpen, SettingsOpen);

            AddToQueueCmd = new SimpleCommand<object>(CanAddToQueueExec, AddToQueueExec);
            RemoveFromQueueCmd = new SimpleCommand<object>(CanRemoveFromQueueExec, RemoveFromQueueExec);
            StartQueueCmd = new SimpleCommand<object>(CanStartQueueExec, StartQueueExec);
            SuspendQueueCmd = new SimpleCommand<object>(CanSuspendQueueExec, SuspendQueueExec);
            GoOnQueueCmd = new SimpleCommand<object>(CanGoOnQueueExec, GoOnQueueExec);
            StopQueueCmd = new SimpleCommand<object>(CanStopQueueExec, StopQueueExec);
        }
        #region 队列操作命令
        private void StopQueueExec(object obj)
        {
            Project.ActionMark = ActionMarkEnum.Stop;
        }

        private bool CanStopQueueExec(object arg)
        {
            if (Project.ProjectState == ProjectStateEnum.Running ||
                Project.ProjectState == ProjectStateEnum.Suspended)
            {
                if (Project.ActionMark != ActionMarkEnum.Stop)
                    return true;
                else
                    return false;
            }
            else
                return false;
        }

        private void GoOnQueueExec(object obj)
        {
            Project.ActionMark = ActionMarkEnum.Null;
            var leftTasks = Project.Tasks.Where(x => x.QueueId != -1 && x.QueueId > Project.CurrentTaskId);
            if (leftTasks.Count() > 0)
            {
                var next = leftTasks.OrderBy(x => x.QueueId).First();
                var nextId = next.QueueId;
                _bgw = new BackgroundWorker();
                _bgw.DoWork += _backWorker_DoWork;
                _bgw.RunWorkerAsync(next);
                Project.ProjectState = ProjectStateEnum.Running;
            }
        }

        private bool CanGoOnQueueExec(object arg)
        {
            if(Project.ProjectState== ProjectStateEnum.Suspended)
                return true;
            return false;
        }

        private void SuspendQueueExec(object obj)
        {
            Project.ActionMark = ActionMarkEnum.Suspend;
        }

        private bool CanSuspendQueueExec(object arg)
        {
            if(Project.ProjectState== ProjectStateEnum.Running&&Project.ActionMark== ActionMarkEnum.Null)
                return true;
            return false;
        }

        private void StartQueueExec(object obj)
        {
            int startId = Project.Tasks.Where(x => x.QueueId != -1&&x.StatuDescription== WorkFlowStateEnum.NotStarted).Min(x => x.QueueId);
            var next = Project.Tasks.FirstOrDefault(x => x.QueueId == startId);
            _bgw = new BackgroundWorker();
            _bgw.DoWork += _backWorker_DoWork;
            _bgw.RunWorkerAsync(next);
            Project.ProjectState = ProjectStateEnum.Running;
        }

        private void _backWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            if(e.Argument is TaskInfo tsk)
            {
                TaskInfo next = (TaskInfo)e.Argument;
                int nextId = next.QueueId;
                while (next != null)
                {
                    next.StatuDescription = WorkFlowStateEnum.Running;
                    next.WorkFlow.Run();
                    Project.CurrentTaskId = next.QueueId;
                    next.StatuDescription = WorkFlowStateEnum.finished;
                    if(Project.ActionMark== ActionMarkEnum.Null)
                    {
                        var others = Project.Tasks.Where(x => x.QueueId != -1 && x.QueueId > nextId);
                        if (others.Count() > 0)
                        {
                            next = others.OrderBy(x => x.QueueId).First();
                            nextId = next.QueueId;
                        }
                        else
                            next = null;
                    }
                    else if(Project.ActionMark ==ActionMarkEnum.Suspend)
                    {
                        Project.ProjectState= ProjectStateEnum.Suspended;
                        return;
                    }
                    else if (Project.ActionMark == ActionMarkEnum.Stop)
                    {
                        Project.ProjectState = ProjectStateEnum.finished;
                        return;
                    }
                }
                Project.ProjectState = ProjectStateEnum.finished;
            }
        }

        private bool CanStartQueueExec(object arg)
        {
            if (Project == null || Project.Tasks == null || Project.Tasks.Count == 0)
                return false;
            if (Project.Tasks.Count(x=>x.QueueId>-1)==0) return false;
            if(Project.ProjectState == ProjectStateEnum.NotStarted) return true;
            return false;
        }

        private void RemoveFromQueueExec(object obj)
        {
            var selectedTasks = Project.Tasks.Where(x => x.IsSelected);
            foreach (var tsk in selectedTasks)
            {
                tsk.QueueId = -1;
                tsk.StatuDescription = WorkFlowStateEnum.NoPlan;
            }
        }

        private bool CanRemoveFromQueueExec(object arg)
        {
            if (Project == null || Project.Tasks == null || Project.Tasks.Count() == 0)
                return false;
            var selectedTasks = Project.Tasks.Where(x => x.IsSelected);
            if(! selectedTasks.Any()) return false;
            foreach (var tsk in selectedTasks)
            {
                if(tsk.WorkFlow.WorkFlowState != WorkFlowStateEnum.NotStarted)
                    return false;
            }
            return true;
        }

        private void AddToQueueExec(object obj)
        {
            int maxQueueId = Project.Tasks.Max(x => x.QueueId);
            int startId = ++maxQueueId;
            var selectedTasks = Project.Tasks.Where(x => x.IsSelected)?.ToList();
            if(selectedTasks.Any())
            {
                foreach (var tsk in selectedTasks)
                {
                    tsk.QueueId = startId;
                    startId++;
                    tsk.StatuDescription = WorkFlowStateEnum.NotStarted;
                }
            }
            if(Project.Tasks.Count(x=>x.QueueId!=-1)>0
                && Project.Tasks.Count(x=>x.WorkFlow.WorkFlowState== WorkFlowStateEnum.Running)==0)
            {
                Project.ProjectState = ProjectStateEnum.NotStarted;
            }
        }

        private bool CanAddToQueueExec(object arg)
        {
            if(Project==null||Project.Tasks==null||Project.Tasks.Count()==0)
                return false;
            var selectedTasks = Project.Tasks.Where(x => x.IsSelected);
            if(!selectedTasks.Any()) return false;
            foreach (var tsk in selectedTasks)
            {
                if(tsk.WorkFlow.WorkFlowState != WorkFlowStateEnum.NoPlan)
                    return false;
            }
            return true ;
        }
        #endregion


        #region 设置对话框打开命令
        private void SettingsOpen(object obj)
        {
            SettingsWind settingsWind = new SettingsWind();
            settingsWind.ShowDialog();
        }

        private bool CanSettingsOpen(object arg)
        {
            return true;
        }
        #endregion
        #region 删除流程
        private bool CanDeleteExecute(object obj)
        {
            var selectedCounts = Project?.Tasks?.Where(x => x.IsSelected);
            if(!selectedCounts.Any())
                return false;
            foreach (var sel in selectedCounts)
            {
                if(sel.StatuDescription!= WorkFlowStateEnum.NoPlan)
                    return false ;
            }
            return true;
        }

        private void DeleteExecute(object obj)
        {
            if(Project!=null&& Project.Tasks !=null)
            {
                var res = Project.Tasks.Count(x => x.IsSelected&&x.QueueId!=-1);
                if (res > 0)
                {
                    Xceed.Wpf.Toolkit.MessageBox.Show("先将选中项移出队列再执行删除", "警告", MessageBoxButton.OK);
                    return;
                }
                MessageBoxResult result = Xceed.Wpf.Toolkit.MessageBox.Show("是否删除选中项？", "请确认", MessageBoxButton.YesNo);
                if (result == MessageBoxResult.Yes)
                {
                    var tobeRemoved = Project?.Tasks.Where(x => x.IsSelected == true).ToList();
                    foreach (var task in tobeRemoved)
                    {
                        Project?.Tasks.Remove(task);
                    }
                }
            }
        }
        #endregion
        #region 新增加命令
        private bool CanNewWorkExecute(object obj)
        {
            if(Directory.Exists(Project.WorkDir))
                return true;
            return false;
        }

        private void NewWorkExecute(object obj)
        {
            AddWorkflow addWfDlg = new AddWorkflow();
            
            if (addWfDlg.ShowDialog() ==true)
            {
                if(addWfDlg.SelectedWf!=null)
                {
                    var clonedWf = addWfDlg.SelectedWf.Clone();
                    if (Project.Tasks == null)
                        Project.Tasks = new ObservableCollection<TaskInfo>();
                    string taskDir = Project.WorkDir + "\\" + addWfDlg.TaskName;
                    Directory.CreateDirectory(taskDir);
                    TaskInfo task = new TaskInfo();
                    if (Project.Tasks.Count <= 0)
                        task.Id = 1;
                    else
                        task.Id = Project.Tasks.Max(x => x.Id) + 1;
                    task.Name = addWfDlg.TaskName;
                    task.WorkFlow = clonedWf;
                    task.WorkFlow.SetWorkDir(taskDir+"\\");
                    task.Path = taskDir;
                    Project.Tasks.Add(task);
                    Tools.CopyDirectory(App.GlobalConfigs.WorkflowFolderPath + task.WorkFlow.Name, taskDir);
                }
            }
        }
        #endregion
        #region 拷贝方案命令
        private bool CanCopyExecute(object obj)
        {
            var selectedCounts = Project?.Tasks?.Where(x => x.IsSelected);
            if (!selectedCounts.Any())
                return false;
            return true;
        }

        private void CopyExecute(object obj)
        {
            var selectedCounts = Project?.Tasks?.Where(x => x.IsSelected).ToList();
            foreach (var tsk in selectedCounts)
            {
                var cloned = tsk.Clone();
                cloned.WorkFlow.WorkFlowState = WorkFlowStateEnum.NoPlan;
                cloned.WorkFlow.StateDescription = null;
                cloned.Id = Project.Tasks.Max(x=>x.Id)+1;
                cloned.Name = cloned.Name + "_copy";
                cloned.StatuDescription = WorkFlowStateEnum.NoPlan;
                cloned.QueueId = -1;
                cloned.QueueIdText = null;
                var taskDir = Directory.CreateDirectory(Project.WorkDir + "\\" + cloned.Name);
                cloned.Path = taskDir.FullName;
                Project.Tasks.Add(cloned);
            }
        }
        #endregion
        #region 设置工作目录命令
        private void SetDirExecute(object obj)
        {
            FolderBrowserDialog openFileDialog = new FolderBrowserDialog();  //选择文件夹
            if (openFileDialog.ShowDialog() == DialogResult.OK)//注意，此处一定要手动引入System.Window.Forms空间，否则你如果使用默认的DialogResult会发现没有OK属性
            {
                //DirectoryInfo dir = new DirectoryInfo(openFileDialog.SelectedPath);
                //var dirs = dir.GetDirectories();
                //foreach ( var d in dirs )
                //{
                //    d.Delete(true);
                //}
                //var files = dir.GetFiles();
                //foreach (var f in files)
                //{
                //    f.Delete();
                //}
                    //System.Windows.MessageBox.Show("此文件夹中含有子文件夹或者文件，请重新选择一个空文件夹作为工作目录", "消息");
                Project.WorkDir = openFileDialog.SelectedPath;
            }
        }

        private bool CanSetDirExecute(object obj)
        {
            if(Project!=null&& Project.Tasks!=null&&Project.Tasks.Count > 0) 
                return false;
            else 
                return true;
        }
#endregion
        public List<AccentColorMenuData> AccentColors { get; set; }

    }

    public class AccentColorMenuData
    {
        public string Name { get; set; }

        public Brush BorderColorBrush { get; set; }

        public Brush ColorBrush { get; set; }

        public AccentColorMenuData()
        {
            this.ChangeAccentCommand = new SimpleCommand<string>(o => true, this.DoChangeTheme);
        }

        public ICommand ChangeAccentCommand { get; }

        protected virtual void DoChangeTheme(string name)
        {

        }
    }
}
